#include "Player.h"
#include "Game.h"
#include "../GameplayStates/GameplayState.h"
#include "../Abilities/Spin.h"
#include "../Abilities\Shield.h"
#include "../Enemies/BasicEnemy.h"
#include "../Enemies/BossStage1.h"
#include "../Abilities/Dash.h"


CPlayer::CPlayer(void) 
{ 


}

void CPlayer::Init(void)
{
	this->m_bPlayerOnPlatform = false;
	this->m_bOnEnemy = false;
	this->m_eType = OBJ_PLAYER;
	m_pD3D = CSGD_Direct3D::GetInstance();
	CGame* pGame = CGame::GetInstance();
	m_pTM = CSGD_TextureManager::GetInstance();
	m_pAM=  CAnimationManager::GetInstance();
	m_pES = CEventSystem::GetInstance();

	CEventSystem::GetInstance()->RegisterClient("tJump", this);
	CEventSystem::GetInstance()->RegisterClient("NEXT",this);
	CEventSystem::GetInstance()->RegisterClient("TakePlayerDamage",this);
	CEventSystem::GetInstance()->RegisterClient("PlayerAttack",this);
	CEventSystem::GetInstance()->RegisterClient("ShieldMode",this);

	m_cAniInfo.SetName("PlayerIdle");
	m_cAniInfo.SetNext("PlayerWalk");
	m_cAniInfo.SetFrame(0);
	m_cAniInfo.SetTime(0);
	//this->SetHeight(m_pAM->GetCHeight(m_cAniInfo));
	//this->SetWidth(m_pAM->GetCWidth(m_cAniInfo));
	SetWidth(32);
	SetHeight(32);
	m_fAttackCooldown = .6f;
	m_fSpinCooldown = 1.0f;
	this->m_nBAttackEffectCount = 0;
	this->m_nSpinAttackEffectCount = 0;
	this->SetDensity(1);
	m_bDead = false;
	m_bSpin = false;
	this->SetPosX((float)CGame::GetInstance()->GetWidth()/2);
	this->SetPosY((float)pGame->GetHeight()- this->GetHeight() - 500);
	this->SetVelX(0);
	this->SetVelY(0);
	this->m_bPlayerOnPlatform = false;
	this->m_bOnEnemy = false;
	this->m_nCurrentHits = 0;
	this->m_nHealth = 100;
	this->m_nHitsNeededForCurrentAbility = 0;
	this->m_nMaxHealth = 100;
	this->m_nPotLifeLoss = 0;
	this->m_bFaceing=false;
	m_bShield =false;
	m_nShieldCount =0;
	m_pFont = new CBitmapFont();
	m_pFont->Load("../resources/XML/DeadlyShadowsFont.xml");
}

CPlayer::~CPlayer(void)
{
	CEventSystem::GetInstance()->UnregisterClientAll(this);
	//FONTS
	if (m_pFont != nullptr)
	{
		delete m_pFont;
		m_pFont = nullptr;
	}

}

void CPlayer::SetPotLifeLoss(int nPotLifeloss)
{
	if(nPotLifeloss > this->m_nHealth)
		m_nPotLifeLoss = m_nHealth;
	else
		m_nPotLifeLoss = nPotLifeloss;
}

void CPlayer::Update(float fElapsedTime)
{
	if(	this->m_bDead==false)
	{
		if(m_fTimeLeftForCurrentAbility > 0)
			m_fTimeLeftForCurrentAbility -= fElapsedTime;

		if(UseAbility() == false)
			this->m_nPotLifeLoss = 0;

		if(this->m_nBAttackEffectCount > 0)
			m_fAttackCooldown -= fElapsedTime;

		if(this->m_nSpinAttackEffectCount > 0)
			m_fSpinCooldown -= fElapsedTime;

		if(m_fAttackCooldown <= 0)
		{
			m_nBAttackEffectCount = 0;
			m_fAttackCooldown = .6f;
		}
		if(m_fSpinCooldown <= 0)
		{
			m_nSpinAttackEffectCount = 0;
			m_fSpinCooldown = 1.0f;
		}
		AbilityFinished();
	}
	CEntity::Update(fElapsedTime);


	m_pAM->Update(fElapsedTime,this->m_cAniInfo);
	//this->SetHeight(m_pAM->GetCHeight(m_cAniInfo));
	//this->SetWidth(m_pAM->GetCWidth(m_cAniInfo));

	if(this->GetPosY() + this->GetHeight() < CGame::GetInstance()->GetHeight() && this->OnPlatform() == false)
	{
		this->SetVelY(this->GetVelY()+5);
	}
	if(this->GetPosY() + this->GetHeight() > (int)CGame::GetInstance()->GetHeight())
	{
		this->SetPosY((float)CGame::GetInstance()->GetHeight()-this->GetHeight());
	}
	CGameplayState::Camera cam = CGameplayState::GetInstance()->GetCamera();
	if(this->GetPosX() <= cam.camPosX)
		if(this->GetVelX() < 0)
		{
			this->SetVelX(0);
			this->SetPosX((float)cam.camPosX);
		}
		if(this->m_bDead==false)
		{
			if(GetShield()==false)
			{
				if(this->m_cAniInfo.GetName()=="PlayerShieldWalk")
					this->m_cAniInfo.SetName("PlayerWalk");
				if(this->m_cAniInfo.GetName()=="PlayerShieldAttack")
					this->m_cAniInfo.SetName("PlayerAttack");
				if(this->m_cAniInfo.GetName()=="PlayerShieldJump")
					this->m_cAniInfo.SetName("PlayerJump");
				if(this->m_cAniInfo.GetName()=="PlayerShieldIdle")
					this->m_cAniInfo.SetName("PlayerIdle");

				if(this->m_cAniInfo.GetName()!="PlayerAttack"&&this->m_cAniInfo.GetName()!="PlayerDash"&&this->m_cAniInfo.GetName()!="PlayerSpin")
				{
					if(this->GetVelX()==0&&this->GetVelY()==0)
					{
						if(this->m_cAniInfo.GetName()=="PlayerJump")
						{
							m_pES->SendEvent("PlayerLand",CGameplayState::GetInstance());

						}
						else if(this->m_cAniInfo.GetName()!="PlayerIdle")
						{


							if(this->m_cAniInfo.GetCurrentFrame()>=2)
							{
								m_cAniInfo.SetFrame(0);

							}
							if(this->m_cAniInfo.GetFrameTime()>0.2)
								m_cAniInfo.SetTime(0);
							this->m_cAniInfo.SetName("PlayerIdle");
							this->m_cAniInfo.SetNext("PlayerWalk");
						}
					}
					else if(this->GetVelY()!=0)
					{
						if(this->m_cAniInfo.GetName()!="PlayerJump")
						{
							if(this->m_cAniInfo.GetCurrentFrame()>=6)
							{
								m_cAniInfo.SetFrame(0);

							}
							if(this->m_cAniInfo.GetFrameTime()>0.2)
								m_cAniInfo.SetTime(0);
							this->m_cAniInfo.SetNext("PlayerIdle");
							this->m_cAniInfo.SetName("PlayerJump");
						}
					}
				}
			}
			else
			{
				if(this->m_cAniInfo.GetName()=="PlayerWalk")
					this->m_cAniInfo.SetName("PlayerShieldWalk");
				if(this->m_cAniInfo.GetName()=="PlayerAttack")
					this->m_cAniInfo.SetName("PlayerShieldAttack");
				if(this->m_cAniInfo.GetName()=="PlayerJump")
					this->m_cAniInfo.SetName("PlayerShieldJump");
				if(this->m_cAniInfo.GetName()=="PlayerIdle")
					this->m_cAniInfo.SetName("PlayerShieldIdle");

				if(this->m_cAniInfo.GetName()!="PlayerShieldAttack"&&this->m_cAniInfo.GetName()!="PlayerShieldDash"&&this->m_cAniInfo.GetName()!="PlayerShieldSpin")
				{
					if(this->GetVelX()==0&&this->GetVelY()==0)
					{
						if(this->m_cAniInfo.GetName()=="PlayerShieldAttack")
						{
						}
						if(this->m_cAniInfo.GetName()!="PlayerShieldIdle")
						{
							if(this->m_cAniInfo.GetCurrentFrame()>=2)
							{
								m_cAniInfo.SetFrame(0);

							}
							if(this->m_cAniInfo.GetFrameTime()>0.2)
								m_cAniInfo.SetTime(0);
							this->m_cAniInfo.SetName("PlayerShieldIdle");
							this->m_cAniInfo.SetNext("PlayerShieldWalk");
						}
					}
					else if(this->GetVelY()!=0)
					{
						if(this->m_cAniInfo.GetName()!="PlayerShieldJump")
						{
							if(this->m_cAniInfo.GetCurrentFrame()>=6)
							{
								m_cAniInfo.SetFrame(0);

							}
							if(this->m_cAniInfo.GetFrameTime()>0.2)
								m_cAniInfo.SetTime(0);
							this->m_cAniInfo.SetNext("PlayerShieldIdle");
							this->m_cAniInfo.SetName("PlayerShieldJump");
						}
					}
				}
			}
		}

}

void CPlayer::Render(void)
{
	this->m_pD3D->GetSprite()->Flush();
	RECT playerRect = {this->GetRect().left - CGameplayState::GetInstance()->GetCamera().camPosX, this->GetRect().top,
		this->GetRect().right - CGameplayState::GetInstance()->GetCamera().camPosX, this->GetRect().bottom};
	m_pD3D->DrawRect(playerRect, 255, 0, 0);
	m_pAM->Render(m_cAniInfo,playerRect.left-10,playerRect.top+15,1,this->GetFacing());
}

bool CPlayer::CheckCollision(IEntity* pOther)
{
	if(CEntity::CheckCollision(pOther) == false)
		return false;
	RECT me = this->GetRect();
	RECT other = pOther->GetRect();
	RECT temp;
	IntersectRect(&temp, &me, &other);
	switch(pOther->GetType())
	{
	case OBJ_EVENT:
		{
			CEventSystem::GetInstance()->SendEvent("tJump", this);
		}
		break;

	case OBJ_TILE:
		{
			if(this->GetPosY() <= other.bottom)
				this->SetVelY(this->GetVelY() + 5);
			if(this->GetPosY() >= other.top-3 )
			{
				if (temp.left !=0)
				{
					this->SetVelX(0);
					this->SetPosX((float)other.left-this->GetWidth());
				}

				if(/*temp.right !=0*/ me.left > other.left && me.left < other.right)
				{
					this->SetVelX(0);
					this->SetPosX((float)other.right);
				}
			}
			if(this->GetVelY() > 0)
			{
				if(temp.bottom !=0)
				{
					this->OnPlatform(true);

					if(this->GetVelY() > 0)
						this->SetVelY(0); 
				}
			}
		}
		break;

	case OBJ_BASIC_ENEMY:
		{
			if(this->GetPosY() <= other.bottom)
				this->SetVelY(this->GetVelY() + 5);
			if(this->GetPosY() >= other.top-3 )
			{
				if (temp.left !=0)
				{
					if(this->m_cAniInfo.GetName()=="PlayerAttack"||this->m_cAniInfo.GetName()=="PlayerShieldAttack")
					{
						if(this->m_nBAttackEffectCount == 0)
							CEventSystem::GetInstance()->SendEvent("take damage",pOther);
						m_nBAttackEffectCount++;
					}
					else
					{
						if(this->GetSpin())
						{
							if(this->m_nSpinAttackEffectCount == 0)
							{
								if(GetShield()==false)
									CEventSystem::GetInstance()->SendEvent("take damage",pOther);
								else
									CEventSystem::GetInstance()->SendEvent("take shield damage",pOther);
							}
							m_nSpinAttackEffectCount++;
						}
					}
					break;
				}
				//if check if in attack mode send collidinh attack mesage
				if(/*temp.right !=0*/ me.left > other.left && me.left < other.right)
				{
					if(this->m_cAniInfo.GetName()=="PlayerAttack"||this->m_cAniInfo.GetName()=="PlayerShieldAttack")
					{
						if(this->m_nBAttackEffectCount == 0)
						{
							if(GetShield()==false)
								CEventSystem::GetInstance()->SendEvent("take damage",pOther);
							else
								CEventSystem::GetInstance()->SendEvent("take shield damage",pOther);
						}
						m_nBAttackEffectCount++;
					}
					else
					{
						if(this->GetSpin())
						{
							if(this->m_nSpinAttackEffectCount == 0)
							{
								if(GetShield()==false)
									CEventSystem::GetInstance()->SendEvent("take damage",pOther);
								else
									CEventSystem::GetInstance()->SendEvent("take shield damage",pOther);
							}
							m_nSpinAttackEffectCount++;
						}
					}
					break;
				}
			}
			if(this->GetVelY() > 0)
			{
				if(temp.bottom !=0)
				{
					//this->OnPlatform(true);

					if(this->GetVelY() > 0)
					{
						this->SetVelY(20);
						CEntity* pEntity = dynamic_cast<CEntity*>(pOther);
						this->OnEnemy(true);
						CBasicEnemy* pEnemy = dynamic_cast<CBasicEnemy*>(pOther);
						pEnemy->SetHealth(0);
						this->m_nCurrentHits++;

					}
				}
			}
		}
		break;

	case OBJ_BOSS1:
		{
			if(this->GetPosY() <= other.bottom)
				this->SetVelY(this->GetVelY() + 5);
			if(this->GetPosY() >= other.top-3 )
			{
				if (temp.left !=0)
				{
					if(this->m_cAniInfo.GetName()=="PlayerAttack"||this->m_cAniInfo.GetName()=="PlayerShieldAttack")
					{
						if(this->m_nBAttackEffectCount == 0)
							CEventSystem::GetInstance()->SendEvent("take damage",pOther);
						m_nBAttackEffectCount++;
					}
					else
					{
						if(this->GetSpin())
						{
							if(this->m_nSpinAttackEffectCount == 0)
							{
								if(GetShield()==false)
									CEventSystem::GetInstance()->SendEvent("take damage",pOther);
								else
									CEventSystem::GetInstance()->SendEvent("take shield damage",pOther);
							}
							m_nSpinAttackEffectCount++;
						}
					}
					break;
				}
				//if check if in attack mode send collidinh attack mesage
				if(/*temp.right !=0*/ me.left > other.left && me.left < other.right)
				{
					if(this->m_cAniInfo.GetName()=="PlayerAttack"||this->m_cAniInfo.GetName()=="PlayerShieldAttack")
					{
						if(this->m_nBAttackEffectCount == 0)
							CEventSystem::GetInstance()->SendEvent("take damage",pOther);
						m_nBAttackEffectCount++;
					}
					else
					{
						if(this->GetSpin())
						{
							if(this->m_nSpinAttackEffectCount == 0)
							{
								if(GetShield()==false)
									CEventSystem::GetInstance()->SendEvent("take damage",pOther);
								else
									CEventSystem::GetInstance()->SendEvent("take shield damage",pOther);
							}
							m_nSpinAttackEffectCount++;
						}
					}
					break;
				}
			}

			if(this->GetVelY() > 0)
			{
				if(temp.bottom !=0)
				{
					//this->OnPlatform(true);
					/*
					if(this->GetVelY() > 0)
					{

					CEntity* pEntity = dynamic_cast<CEntity*>(pOther);
					this->OnEnemy(true);
					CBossStage1* pEnemy = dynamic_cast<CBossStage1*>(pOther);
					pEnemy->SetHealth(0);
					this->m_nCurrentHits++;

					}
					*/
				}
			}

		}
		break;


	}
	return true;
}

void CPlayer::AddAbility(CAbilities* pAbility)
{
	switch(pAbility->GetCode())
	{
	case 0:
		{
			CDash* pDash = dynamic_cast<CDash*>(pAbility);
			pDash->Init();
			this->m_pPlayerAbilities.push_back(pDash);
			//face true is right
			if (m_bFaceing)
				SetPosX(GetPosX() - 100);
			else 
				SetPosX(GetPosX() + 100);
			//may want to check collision
		}
		break;
	case 2:
		{
			CSpin* pSpin = dynamic_cast<CSpin*>(pAbility);
			pSpin->Init();
			this->m_pPlayerAbilities.push_back(pSpin);
		}
		break;
	case 1:
		{
			CShield* pShield = dynamic_cast<CShield*>(pAbility);
			pShield->Init();
			this->m_pPlayerAbilities.push_back(pShield);
			ModShieldCount(1);
			SetShield(true);
		}
		break;
	}
}

bool CPlayer::UseAbility(void)
{
	if(this->m_pPlayerAbilities.size() > 0)
	{
		auto iter = this->m_pPlayerAbilities.begin();
		if((*iter)->GetCode() ==0)
		{
			this->m_cAniInfo.SetFrame(0);
			this->m_cAniInfo.SetTime(0);
			if(this->GetShield()==true)
			{
				this->m_cAniInfo.SetName("PlayerShieldDash");
				this->m_cAniInfo.SetNext("PlayerShieldWalk");
			}
			else
			{
				this->m_cAniInfo.SetName("PlayerDash");
				this->m_cAniInfo.SetNext("PlayerWalk");
			}	
		}
		else if((*iter)->GetCode() ==2)
		{
			this->m_cAniInfo.SetFrame(0);
			this->m_cAniInfo.SetTime(0);
			if(this->GetShield()==true)
			{
				this->m_cAniInfo.SetName("PlayerShieldSpin");
				this->m_cAniInfo.SetNext("PlayerShieldWalk");
			}
			else
			{
				this->m_cAniInfo.SetName("PlayerSpin");
				this->m_cAniInfo.SetNext("PlayerWalk");
			}	
		}
		this->m_nHitsNeededForCurrentAbility = (*iter)->GetHitRequirement();
		this->m_nPotLifeLoss = (*iter)->GetHealthCost();
		if(this->m_nHealth - this->m_nPotLifeLoss < 0)
			this->m_nPotLifeLoss = this->m_nHealth;
		return true;
	}
	return false;
}

void CPlayer::AbilityFinished(void)
{
	if(this->m_nCurrentHits >= this->m_nHitsNeededForCurrentAbility && this->m_pPlayerAbilities.size() > 0)
	{
		auto iter = this->m_pPlayerAbilities.begin();

		if((*iter)->GetCode() ==1)
		{
			if(GetShieldCount()==0)
			{
				SetShield(false);
			}
			else
			{
				ModShieldCount(-1);
			}
		}

		this->m_pPlayerAbilities.pop_front();
		if(this->m_pPlayerAbilities.size() > 0)
		{
			iter = this->m_pPlayerAbilities.begin();
			this->m_fTimeLeftForCurrentAbility = (*iter)->GetAbilityTimer();
			this->m_nPotLifeLoss = (*iter)->GetHealthCost();
			if(this->m_nPotLifeLoss > this->m_nHealth)
				this->m_nPotLifeLoss = this->m_nHealth;
		}
	}
	if(this->m_fTimeLeftForCurrentAbility <= 0 && this->m_nCurrentHits < this->m_nHitsNeededForCurrentAbility && this->m_pPlayerAbilities.size() > 0)
	{
		this->m_nHealth -= this->m_nPotLifeLoss;
		this->m_nPotLifeLoss = 0;
		this->m_nHitsNeededForCurrentAbility = 0;
		auto iter = this->m_pPlayerAbilities.begin();
		if((*iter)->GetCode() ==1)
		{
			if(GetShieldCount()==0)
			{
				SetShield(false);
			}
			else
			{
				ModShieldCount(-1);
				if(GetShieldCount()==0)
					SetShield(false);
			}
		}
		this->m_pPlayerAbilities.pop_front();
		if(this->m_pPlayerAbilities.size() > 0)
		{
			iter = this->m_pPlayerAbilities.begin();
			this->m_fTimeLeftForCurrentAbility = (*iter)->GetAbilityTimer();
			this->m_nPotLifeLoss = (*iter)->GetHealthCost();
			if(this->m_nPotLifeLoss > this->m_nHealth)
				this->m_nPotLifeLoss = this->m_nHealth;
		}
	}
}

void CPlayer::UpdateTimeLeft(void)
{
	if(this->m_pPlayerAbilities.size() == 1)
	{
		auto iter = this->m_pPlayerAbilities.begin();
		this->m_fTimeLeftForCurrentAbility = (*iter)->GetAbilityTimer();
		this->m_nPotLifeLoss = (*iter)->GetHealthCost();
		if(this->m_nPotLifeLoss > this->m_nHealth)
			this->m_nPotLifeLoss = this->m_nHealth;
	}
}
void CPlayer::HandleEvent(CNEvent* pEvent)
{
	if(pEvent->GetParam() == nullptr || pEvent->GetParam() == this)
	{
		if(pEvent->GetEventID() == "tJump")
		{
			m_pFont->Print("Spacebar to Jump", 400, 400, 1.5f, D3DXCOLOR(128,128,128,255));
		}
	}

	if (pEvent->GetEventID()=="NEXT")
	{


		if(GetShield()==true)
		{
			m_cAniInfo.SetName("PlayerShieldWalk");
			m_cAniInfo.SetNext("PlayerShieldAttack");
			m_cAniInfo.SetTime(0);
			m_cAniInfo.SetFrame(0);

		}
		else
		{
			m_cAniInfo.SetName("PlayerWalk");
			m_cAniInfo.SetNext("PlayerAttack");
			m_cAniInfo.SetTime(0);
			m_cAniInfo.SetFrame(0);
		}

	}

	if(pEvent->GetEventID()=="TakePlayerDamage")
	{

		if(GetShield()==true)
		{
			m_nHealth+=2;
		}
		else
			m_nHealth-=10;
	}

	if (pEvent->GetEventID()=="PlayerAttack")
	{

		if(GetShield()==true)
		{
			m_cAniInfo.SetTime(0);
			m_cAniInfo.SetFrame(0);
			m_cAniInfo.SetName("PlayerShieldAttack");
			m_cAniInfo.SetNext("PlayerShieldWalk");


		}
		else
		{
			m_cAniInfo.SetTime(0);
			m_cAniInfo.SetFrame(0);
			m_cAniInfo.SetName("PlayerAttack");
			m_cAniInfo.SetNext("PlayerWalk");
		}
	}

}